package com.stock.demo.framework.ui.view;

import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.stock.demo.R;
import com.stock.demo.framework.ui.NetCompleteBean;
import com.stock.demo.framework.ui.NetErrorBean;
import com.stock.demo.framework.ui.NetPageState;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

import static com.stock.demo.framework.ui.NetPageState.EMPTY;
import static com.stock.demo.framework.ui.NetPageState.ERROR;
import static com.stock.demo.framework.ui.NetPageState.LOADING;
import static com.stock.demo.framework.ui.NetPageState.SUCCESS;

/**
 * Created by XuZhaoyu on 2017/5/15.
 */

public abstract class BaseNetPage extends FrameLayout {

    private View mLoadingView;
    private View mErrorView;
    private View mEmptyView;
    private View mSuccessView;

    public BaseNetPage(@NonNull Context context) {
        this(context, null);
    }

    public BaseNetPage(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseNetPage(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        if (mSuccessView == null) {
            mSuccessView = createSuccessView();
        }
        if (mLoadingView == null) {
            mLoadingView = createLoadingView();
        }
        if (mErrorView == null) {
            mErrorView = createErrorView();
        }
        if (mEmptyView == null) {
            mEmptyView = createEmptyView();
        }

        addView(mSuccessView);
        addView(mLoadingView);
        addView(mErrorView);
        addView(mEmptyView);

        showPage();

        mErrorView.findViewById(R.id.tv_base_net_page_error).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mStates.clear();
                onReloadClick(v);
                mCurrentState = LOADING;
            }
        });
    }

    private void showPage() {
        Observable.create(new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(@io.reactivex.annotations.NonNull ObservableEmitter e) throws Exception {
                getEmitter(e);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Object>() {
            @Override
            public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
                changePageState();
            }

            @Override
            public void onNext(@io.reactivex.annotations.NonNull Object netBean) {
                checkNetData(netBean);
                if (netBean instanceof NetCompleteBean) {
                    if (mStates.size() == 0) {
                        return;
                    }
                    for (NetPageState state : mStates) {
                        if (state == ERROR) {
                            mCurrentState = ERROR;
                            break;
                        } else if (state == EMPTY) {
                            mCurrentState = EMPTY;
                            break;
                        }
                    }
                    if (mCurrentState == LOADING) {
                        mCurrentState = SUCCESS;
                    }
                    changePageState();
                    mStates.clear();
                    mCurrentState = LOADING;
                }
            }

            @Override
            public void onError(@io.reactivex.annotations.NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }

    /**
     * 用于记录一次或多次请求服务器返回的结果的集合
     */
    private List<NetPageState> mStates = new ArrayList<>();

    /**
     * 根据服务器返回的数据，记录请求的结果
     *
     * @param netBean 服务器返回的json解析对象
     */
    private void checkNetData(Object netBean) {
        if (netBean instanceof NetCompleteBean) {
            return;
        }
        if (netBean instanceof NetErrorBean) {//返回的数据为NetErrorBean，则返回ERROR
            mStates.add(ERROR);
        } else {//返回的数据不为NetErrorBean
            if (netBean instanceof List) {//返回的数据为集合
                if (((List) netBean).size() == 0) {//集合的长度为0，则返回EMPTY
                    mStates.add(EMPTY);
                } else {//集合长度不为0，则返回SUCCESS
                    mStates.add(SUCCESS);
                }
            } else {//返回的数据为单个bean对象，则返回SUCCESS
                mStates.add(SUCCESS);
            }
        }
    }

    private NetPageState mCurrentState = LOADING;

    /**
     * 根据mCurrentState自动切换页面的显示
     */
    public void changePageState() {
        mLoadingView.setVisibility(INVISIBLE);
        mErrorView.setVisibility(INVISIBLE);
        mEmptyView.setVisibility(INVISIBLE);
        mSuccessView.setVisibility(INVISIBLE);
        switch (mCurrentState) {
            case LOADING:
                mLoadingView.setVisibility(VISIBLE);
                if (mListener != null) {
                    mListener.onNetStateChange(LOADING);
                }
                break;
            case ERROR:
                mErrorView.setVisibility(VISIBLE);
                if (mListener != null) {
                    mListener.onNetStateChange(ERROR);
                }
                break;
            case EMPTY:
                mEmptyView.setVisibility(VISIBLE);
                if (mListener != null) {
                    mListener.onNetStateChange(EMPTY);
                }
                break;
            case SUCCESS:
                mSuccessView.setVisibility(VISIBLE);
                if (mListener != null) {
                    mListener.onNetStateChange(SUCCESS);
                }
                break;
        }
    }

    public interface OnNetStateChangeListener {
        void onNetStateChange(NetPageState state);
    }

    private OnNetStateChangeListener mListener;

    /**
     * 设置页面网络状态切换的监听
     *
     * @param listener
     */
    public void setOnNetStateChangeListener(OnNetStateChangeListener listener) {
        mListener = listener;
    }

    public View createEmptyView() {
        return LayoutInflater.from(getContext()).inflate(R.layout.page_net_empty, this, false);
    }

    public View createErrorView() {
        return LayoutInflater.from(getContext()).inflate(R.layout.page_net_error, this, false);
    }

    public View createLoadingView() {
        mLoadingView = LayoutInflater.from(getContext()).inflate(R.layout.page_net_loading, this, false);
        ImageView ivLoading = (ImageView) mLoadingView.findViewById(R.id.iv_loading_page);
        ivLoading.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.loading_animation));
        return mLoadingView;
    }

    public abstract View createSuccessView();

    public abstract void onReloadClick(View v);

    public abstract void getEmitter(ObservableEmitter emitter);

}
